/*
 * 文件名: index.js
 * 作者: 破浪前行·吴
 * 创建日期: 2024/5/10
 * 描述: 使用sheetjs导出xlsx
 */
const TreeNode = require("./TreeNode");
const XLSX = require("xlsx");

// 创建根节点
const ORGANIZATION = "organization";
const originTreeNode = new TreeNode();
originTreeNode.id = ORGANIZATION;
const a = new TreeNode();
a.name = "1";
const aa = new TreeNode();
aa.name = "11";
const aaa = new TreeNode();
aaa.name = "111";
const aab = new TreeNode();
aab.name = "112";
aa.addChildNode(aaa, aab);
const ab = new TreeNode();
ab.name = "12";
const ac = new TreeNode();
ac.name = "13";
a.addChildNode(aa, ab, ac);
const b = new TreeNode();
b.name = "2";
const ba = new TreeNode();
ba.name = "21";
const bb = new TreeNode();
bb.name = "22";
b.addChildNode(ba, bb);
originTreeNode.addChildNode(a, b);

/**
 * @description 打平数据源
 * @param {TreeNode} treeNode 节点
 * @param {boolean} isSelf 是否包含自己
 * @returns {TreeNode[]}
 */
const flatTreeNodeMethod = (treeNode, isSelf = false) => {
  const searchResult = [];
  const loop = (list) => {
    for (let i = 0; i < list.length; i++) {
      const item = list[i];
      searchResult.push(item);
      if (item.children && item.children.length) {
        loop(item.children);
      }
    }
  };
  loop(isSelf ? [treeNode] : treeNode.children);
  return searchResult;
};

const flatTreeNode = flatTreeNodeMethod(originTreeNode);

// 每一列的数据
const columnListMap = new Map();
let maxDepth = 1;
let hasChildrenNumber = 0;
for (let index = 0; index < flatTreeNode.length; index++) {
  const element = flatTreeNode[index];
  const depth = element.getChainParent().length; // 当前节点深度
  const values = columnListMap.get(depth) || [];
  values.push(element);
  columnListMap.set(depth, values);
  if (depth > maxDepth) {
    maxDepth = depth;
  }
  if (element.children && element.children.length) {
    hasChildrenNumber++;
  }
}

const aoa = [];
for (let row = 0; row < flatTreeNode.length - hasChildrenNumber; row++) {
  aoa[row] = [];
  for (let col = 0; col < maxDepth; col++) {
    aoa[row][col] = null;
  }
}

/**
 * 获取当前节点所有没有子级的子节点数量
 * @param {TreeNode} element
 * @returns {number}
 */
const getCurrentNodeNoHasChildrenNumber = (element) => {
  return (
    flatTreeNodeMethod(element).filter(
      (node) => !node.children || node.children.length === 0
    ).length || 1
  );
};

/**
 * 获取当前下标之前节点的总行数
 * @param {TreeNode[]} list
 * @param {number} currentIndex
 * @returns {number}
 */
const getRowNumber = (list, currentIndex) => {
  let total = 0;
  for (let index = 0; index < currentIndex; index++) {
    const element = list[index];
    total += getCurrentNodeNoHasChildrenNumber(element);
  }
  return total;
};

// 合并范围
const ranges = [];
for (let depth = 1; depth <= maxDepth; depth++) {
  const values = columnListMap.get(depth);
  if (values) {
    const col = depth - 1;
    // 当前列偏移量（占位符）
    let offsetRow = 0;
    for (let index = 0; index < values.length; index++) {
      const element = values[index];
      let row = getRowNumber(values, index) + offsetRow;
      // 检测当前是否有占位符或值
      const loop = () => {
        if (aoa[row][col] === "" || aoa[row][col]) {
          row += 1;
          offsetRow += 1;
          loop();
        }
      };
      loop();
      // 没有子节点 当前行当前列后填入占位符 最后一列不执行
      if (
        (!element.children || element.children.length === 0) &&
        !(col === maxDepth - 1)
      ) {
        for (let ccindex = col + 1; ccindex < maxDepth; ccindex++) {
          aoa[row][ccindex] = "";
        }
      } else if (element.children && element.children.length > 1) {
        // 子节点大于1 计算合并范围
        const range = {
          s: {
            r: row,
            c: col,
          },
          e: {
            r: row + getCurrentNodeNoHasChildrenNumber(element) - 1,
            c: col,
          },
        };
        ranges.push(range);
      }
      aoa[row][col] = element.name;
    }
  }
}
const workSheet = XLSX.utils.aoa_to_sheet(aoa);
workSheet["!merges"] = ranges;
const workBook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workBook, workSheet, "Tree");
XLSX.writeFile(workBook, "tree.xlsx");
